package com.sirius.meta.mall.gateway.util.jwt;

import com.nimbusds.jose.*;
import com.nimbusds.jose.crypto.MACSigner;
import com.nimbusds.jose.crypto.MACVerifier;
import com.nimbusds.jwt.JWTClaimsSet;
import com.nimbusds.jwt.SignedJWT;
import com.sirius.meta.mall.gateway.exception.extend.ResultException;
import lombok.extern.slf4j.Slf4j;

import java.text.ParseException;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;
import java.util.Objects;

/**
 * @author Surging
 * @version 1.0
 * @date 2021/5/11 下午5:53
 * @desc:
 */
@Slf4j
public class JWTHS256 {

    /**
     * 创建秘钥
     */
    private static final byte[] SECRET = "kichinacnbeijin2021kichinacnbeijin2021".getBytes();

    /**
     * 过期时间5秒
     */
    private static final long EXPIRE_TIME = 60 * 60 * 1000 * 10L;



    /**
     * 生成Token
     * @param mobile 用户号码
     * @param source 用户来源
     * @param serialNumber token序列号
     * @return
     */
    public static String buildJWT(String mobile, String source, String serialNumber) {
        try {
            /**
             * 1.创建一个32-byte的密匙
             */
            MACSigner macSigner = new MACSigner(SECRET);
            /**
             * 2. 建立payload 载体
             */
            JWTClaimsSet claimsSet = new JWTClaimsSet.Builder()
                    .subject("doi")
                    .issuer("http://www.doiduoyi.com")
                    .expirationTime(new Date(System.currentTimeMillis() + EXPIRE_TIME))
                    .claim("mobile", mobile)
                    .claim("source", source)
                    .claim("serialNumber", serialNumber)
                    .build();

            /**
             * 3. 建立签名
             */
            SignedJWT signedJWT = new SignedJWT(new JWSHeader(JWSAlgorithm.HS256), claimsSet);
            signedJWT.sign(macSigner);

            /**
             * 4. 生成token
             */
            String token = signedJWT.serialize();
            return token;
        } catch (KeyLengthException e) {
            e.printStackTrace();
        } catch (JOSEException e) {
            e.printStackTrace();
        }
        return null;
    }


    /**
     * 校验token
     *
     * @param token
     * @return
     */
    public static Map<String, Object> decryptToken(String token) {
        Map<String, Object> tokenMap = new HashMap<>();
        try {
            SignedJWT jwt = SignedJWT.parse(token);
            JWSVerifier verifier = new MACVerifier(SECRET);
            //校验是否有效
            if (!jwt.verify(verifier)) {
                throw new ResultException("Token 无效");
            }
            //校验超时
            Date expirationTime = jwt.getJWTClaimsSet().getExpirationTime();
            Date date = new Date();
            if (date.after(expirationTime)) {
                throw new ResultException("Token 已过期");
            }

            Long expireTime = expirationTime.getTime() - System.currentTimeMillis();
            //获取载体中的数据
            Object mobile = jwt.getJWTClaimsSet().getClaim("mobile");
            Object source = jwt.getJWTClaimsSet().getClaim("source");
            Object serialNumber = jwt.getJWTClaimsSet().getClaim("serialNumber");
            Object account = jwt.getJWTClaimsSet().getClaim("ACCOUNT");
            //是否有openUid
            if (Objects.isNull(mobile)&&Objects.isNull(account)) {
                throw new ResultException("账号为空");

            }
            if (Objects.nonNull(account)){
                tokenMap.put("value", account);
            }else {
                tokenMap.put("value", mobile);
            }
            tokenMap.put("source", source);
            tokenMap.put("serialNumber", serialNumber);
            tokenMap.put("expire", expireTime);
            return tokenMap;
        } catch (ParseException e) {
            throw new ResultException("Token 无效");
        } catch (JOSEException e) {
            throw new ResultException("Token 无效");
        }
    }


}
